home *** CD-ROM | disk | FTP | other *** search
/ Komputer for Alle 2004 #2 / K-CD-2-2004.ISO / OpenOffice Sv / f_0397 / python-core-2.2.2 / lib / test / test_sax.py < prev    next >
Encoding:
Python Source  |  2003-07-18  |  19.7 KB  |  708 lines

  1. # regression test for SAX 2.0
  2. # $Id: test_sax.py,v 1.19.8.2 2002/10/08 19:49:35 fdrake Exp $
  3.  
  4. from xml.sax import make_parser, ContentHandler, \
  5.                     SAXException, SAXReaderNotAvailable, SAXParseException
  6. try:
  7.     make_parser()
  8. except SAXReaderNotAvailable:
  9.     # don't try to test this module if we cannot create a parser
  10.     raise ImportError("no XML parsers available")
  11. from xml.sax.saxutils import XMLGenerator, escape, quoteattr, XMLFilterBase
  12. from xml.sax.expatreader import create_parser
  13. from xml.sax.xmlreader import InputSource, AttributesImpl, AttributesNSImpl
  14. from cStringIO import StringIO
  15. from test_support import verify, verbose, TestFailed, findfile
  16. import os
  17.  
  18. # ===== Utilities
  19.  
  20. tests = 0
  21. fails = 0
  22.  
  23. def confirm(outcome, name):
  24.     global tests, fails
  25.  
  26.     tests = tests + 1
  27.     if outcome:
  28.         print "Passed", name
  29.     else:
  30.         print "Failed", name
  31.         fails = fails + 1
  32.  
  33. def test_make_parser2():
  34.     try:
  35.         # Creating parsers several times in a row should succeed.
  36.         # Testing this because there have been failures of this kind
  37.         # before.
  38.         from xml.sax import make_parser
  39.         p = make_parser()
  40.         from xml.sax import make_parser
  41.         p = make_parser()
  42.         from xml.sax import make_parser
  43.         p = make_parser()
  44.         from xml.sax import make_parser
  45.         p = make_parser()
  46.         from xml.sax import make_parser
  47.         p = make_parser()
  48.         from xml.sax import make_parser
  49.         p = make_parser()
  50.     except:
  51.         return 0
  52.     else:
  53.         return p
  54.  
  55.  
  56. # ===========================================================================
  57. #
  58. #   saxutils tests
  59. #
  60. # ===========================================================================
  61.  
  62. # ===== escape
  63.  
  64. def test_escape_basic():
  65.     return escape("Donald Duck & Co") == "Donald Duck & Co"
  66.  
  67. def test_escape_all():
  68.     return escape("<Donald Duck & Co>") == "<Donald Duck & Co>"
  69.  
  70. def test_escape_extra():
  71.     return escape("Hei pσ deg", {"σ" : "å"}) == "Hei på deg"
  72.  
  73. # ===== quoteattr
  74.  
  75. def test_quoteattr_basic():
  76.     return quoteattr("Donald Duck & Co") == '"Donald Duck & Co"'
  77.  
  78. def test_single_quoteattr():
  79.     return (quoteattr('Includes "double" quotes')
  80.             == '\'Includes "double" quotes\'')
  81.  
  82. def test_double_quoteattr():
  83.     return (quoteattr("Includes 'single' quotes")
  84.             == "\"Includes 'single' quotes\"")
  85.  
  86. def test_single_double_quoteattr():
  87.     return (quoteattr("Includes 'single' and \"double\" quotes")
  88.             == "\"Includes 'single' and "double" quotes\"")
  89.  
  90. # ===== make_parser
  91.  
  92. def test_make_parser():
  93.     try:
  94.         # Creating a parser should succeed - it should fall back
  95.         # to the expatreader
  96.         p = make_parser(['xml.parsers.no_such_parser'])
  97.     except:
  98.         return 0
  99.     else:
  100.         return p
  101.  
  102.  
  103. # ===== XMLGenerator
  104.  
  105. start = '<?xml version="1.0" encoding="iso-8859-1"?>\n'
  106.  
  107. def test_xmlgen_basic():
  108.     result = StringIO()
  109.     gen = XMLGenerator(result)
  110.     gen.startDocument()
  111.     gen.startElement("doc", {})
  112.     gen.endElement("doc")
  113.     gen.endDocument()
  114.  
  115.     return result.getvalue() == start + "<doc></doc>"
  116.  
  117. def test_xmlgen_content():
  118.     result = StringIO()
  119.     gen = XMLGenerator(result)
  120.  
  121.     gen.startDocument()
  122.     gen.startElement("doc", {})
  123.     gen.characters("huhei")
  124.     gen.endElement("doc")
  125.     gen.endDocument()
  126.  
  127.     return result.getvalue() == start + "<doc>huhei</doc>"
  128.  
  129. def test_xmlgen_pi():
  130.     result = StringIO()
  131.     gen = XMLGenerator(result)
  132.  
  133.     gen.startDocument()
  134.     gen.processingInstruction("test", "data")
  135.     gen.startElement("doc", {})
  136.     gen.endElement("doc")
  137.     gen.endDocument()
  138.  
  139.     return result.getvalue() == start + "<?test data?><doc></doc>"
  140.  
  141. def test_xmlgen_content_escape():
  142.     result = StringIO()
  143.     gen = XMLGenerator(result)
  144.  
  145.     gen.startDocument()
  146.     gen.startElement("doc", {})
  147.     gen.characters("<huhei&")
  148.     gen.endElement("doc")
  149.     gen.endDocument()
  150.  
  151.     return result.getvalue() == start + "<doc><huhei&</doc>"
  152.  
  153. def test_xmlgen_attr_escape():
  154.     result = StringIO()
  155.     gen = XMLGenerator(result)
  156.  
  157.     gen.startDocument()
  158.     gen.startElement("doc", {"a": '"'})
  159.     gen.startElement("e", {"a": "'"})
  160.     gen.endElement("e")
  161.     gen.startElement("e", {"a": "'\""})
  162.     gen.endElement("e")
  163.     gen.endElement("doc")
  164.     gen.endDocument()
  165.  
  166.     return result.getvalue() == start \
  167.            + "<doc a='\"'><e a=\"'\"></e><e a=\"'"\"></e></doc>"
  168.  
  169. def test_xmlgen_ignorable():
  170.     result = StringIO()
  171.     gen = XMLGenerator(result)
  172.  
  173.     gen.startDocument()
  174.     gen.startElement("doc", {})
  175.     gen.ignorableWhitespace(" ")
  176.     gen.endElement("doc")
  177.     gen.endDocument()
  178.  
  179.     return result.getvalue() == start + "<doc> </doc>"
  180.  
  181. ns_uri = "http://www.python.org/xml-ns/saxtest/"
  182.  
  183. def test_xmlgen_ns():
  184.     result = StringIO()
  185.     gen = XMLGenerator(result)
  186.  
  187.     gen.startDocument()
  188.     gen.startPrefixMapping("ns1", ns_uri)
  189.     gen.startElementNS((ns_uri, "doc"), "ns1:doc", {})
  190.     # add an unqualified name
  191.     gen.startElementNS((None, "udoc"), None, {})
  192.     gen.endElementNS((None, "udoc"), None)
  193.     gen.endElementNS((ns_uri, "doc"), "ns1:doc")
  194.     gen.endPrefixMapping("ns1")
  195.     gen.endDocument()
  196.  
  197.     return result.getvalue() == start + \
  198.            ('<ns1:doc xmlns:ns1="%s"><udoc></udoc></ns1:doc>' %
  199.                                          ns_uri)
  200.  
  201. # ===== XMLFilterBase
  202.  
  203. def test_filter_basic():
  204.     result = StringIO()
  205.     gen = XMLGenerator(result)
  206.     filter = XMLFilterBase()
  207.     filter.setContentHandler(gen)
  208.  
  209.     filter.startDocument()
  210.     filter.startElement("doc", {})
  211.     filter.characters("content")
  212.     filter.ignorableWhitespace(" ")
  213.     filter.endElement("doc")
  214.     filter.endDocument()
  215.  
  216.     return result.getvalue() == start + "<doc>content </doc>"
  217.  
  218. # ===========================================================================
  219. #
  220. #   expatreader tests
  221. #
  222. # ===========================================================================
  223.  
  224. # ===== XMLReader support
  225.  
  226. def test_expat_file():
  227.     parser = create_parser()
  228.     result = StringIO()
  229.     xmlgen = XMLGenerator(result)
  230.  
  231.     parser.setContentHandler(xmlgen)
  232.     parser.parse(open(findfile("test"+os.extsep+"xml")))
  233.  
  234.     return result.getvalue() == xml_test_out
  235.  
  236. # ===== DTDHandler support
  237.  
  238. class TestDTDHandler:
  239.  
  240.     def __init__(self):
  241.         self._notations = []
  242.         self._entities  = []
  243.  
  244.     def notationDecl(self, name, publicId, systemId):
  245.         self._notations.append((name, publicId, systemId))
  246.  
  247.     def unparsedEntityDecl(self, name, publicId, systemId, ndata):
  248.         self._entities.append((name, publicId, systemId, ndata))
  249.  
  250. def test_expat_dtdhandler():
  251.     parser = create_parser()
  252.     handler = TestDTDHandler()
  253.     parser.setDTDHandler(handler)
  254.  
  255.     parser.feed('<!DOCTYPE doc [\n')
  256.     parser.feed('  <!ENTITY img SYSTEM "expat.gif" NDATA GIF>\n')
  257.     parser.feed('  <!NOTATION GIF PUBLIC "-//CompuServe//NOTATION Graphics Interchange Format 89a//EN">\n')
  258.     parser.feed(']>\n')
  259.     parser.feed('<doc></doc>')
  260.     parser.close()
  261.  
  262.     return handler._notations == [("GIF", "-//CompuServe//NOTATION Graphics Interchange Format 89a//EN", None)] and \
  263.            handler._entities == [("img", None, "expat.gif", "GIF")]
  264.  
  265. # ===== EntityResolver support
  266.  
  267. class TestEntityResolver:
  268.  
  269.     def resolveEntity(self, publicId, systemId):
  270.         inpsrc = InputSource()
  271.         inpsrc.setByteStream(StringIO("<entity/>"))
  272.         return inpsrc
  273.  
  274. def test_expat_entityresolver():
  275.     parser = create_parser()
  276.     parser.setEntityResolver(TestEntityResolver())
  277.     result = StringIO()
  278.     parser.setContentHandler(XMLGenerator(result))
  279.  
  280.     parser.feed('<!DOCTYPE doc [\n')
  281.     parser.feed('  <!ENTITY test SYSTEM "whatever">\n')
  282.     parser.feed(']>\n')
  283.     parser.feed('<doc>&test;</doc>')
  284.     parser.close()
  285.  
  286.     return result.getvalue() == start + "<doc><entity></entity></doc>"
  287.  
  288. # ===== Attributes support
  289.  
  290. class AttrGatherer(ContentHandler):
  291.  
  292.     def startElement(self, name, attrs):
  293.         self._attrs = attrs
  294.  
  295.     def startElementNS(self, name, qname, attrs):
  296.         self._attrs = attrs
  297.  
  298. def test_expat_attrs_empty():
  299.     parser = create_parser()
  300.     gather = AttrGatherer()
  301.     parser.setContentHandler(gather)
  302.  
  303.     parser.feed("<doc/>")
  304.     parser.close()
  305.  
  306.     return verify_empty_attrs(gather._attrs)
  307.  
  308. def test_expat_attrs_wattr():
  309.     parser = create_parser()
  310.     gather = AttrGatherer()
  311.     parser.setContentHandler(gather)
  312.  
  313.     parser.feed("<doc attr='val'/>")
  314.     parser.close()
  315.  
  316.     return verify_attrs_wattr(gather._attrs)
  317.  
  318. def test_expat_nsattrs_empty():
  319.     parser = create_parser(1)
  320.     gather = AttrGatherer()
  321.     parser.setContentHandler(gather)
  322.  
  323.     parser.feed("<doc/>")
  324.     parser.close()
  325.  
  326.     return verify_empty_nsattrs(gather._attrs)
  327.  
  328. def test_expat_nsattrs_wattr():
  329.     parser = create_parser(1)
  330.     gather = AttrGatherer()
  331.     parser.setContentHandler(gather)
  332.  
  333.     parser.feed("<doc xmlns:ns='%s' ns:attr='val'/>" % ns_uri)
  334.     parser.close()
  335.  
  336.     attrs = gather._attrs
  337.  
  338.     return attrs.getLength() == 1 and \
  339.            attrs.getNames() == [(ns_uri, "attr")] and \
  340.            attrs.getQNames() == ["ns:attr"] and \
  341.            len(attrs) == 1 and \
  342.            attrs.has_key((ns_uri, "attr")) and \
  343.            attrs.keys() == [(ns_uri, "attr")] and \
  344.            attrs.get((ns_uri, "attr")) == "val" and \
  345.            attrs.get((ns_uri, "attr"), 25) == "val" and \
  346.            attrs.items() == [((ns_uri, "attr"), "val")] and \
  347.            attrs.values() == ["val"] and \
  348.            attrs.getValue((ns_uri, "attr")) == "val" and \
  349.            attrs[(ns_uri, "attr")] == "val"
  350.  
  351. class ElemGatherer(ContentHandler):
  352.     def __init__(self):
  353.         self.events = []
  354.     def startElementNS(self, pair, qname, attrs):
  355.         self.events.append(('start', pair, qname))
  356.     def endElementNS(self, pair, qname):
  357.         self.events.append(('end', pair, qname))
  358.  
  359. def check_expat_nsdecl(text, expected):
  360.     parser = create_parser(1)
  361.     handler = ElemGatherer()
  362.     parser.setContentHandler(handler)
  363.     parser.feed(text)
  364.     parser.close()
  365.     if verbose and handler.events != expected:
  366.         from pprint import pprint
  367.         print "Expected:"
  368.         pprint(expected)
  369.         print "Received:"
  370.         pprint(handler.events)
  371.     return handler.events == expected
  372.  
  373. def test_expat_nsdecl_single():
  374.     return check_expat_nsdecl(
  375.         "<abc xmlns='http://xml.python.org/'></abc>", [
  376.             ("start", ("http://xml.python.org/", "abc"), "abc"),
  377.             ("end", ("http://xml.python.org/", "abc"), "abc"),
  378.             ])
  379.  
  380. def test_expat_nsdecl_pair_same():
  381.     # XXX This shows where xml.sax.expatreader can use the wrong
  382.     # prefix when more than one is in scope for a particular URI.
  383.     # We still want to exercise this code since previous versions got
  384.     # the namespace handling wrong in more severe ways (exceptions
  385.     # that should not have happened).
  386.     return check_expat_nsdecl(
  387.         "<abc xmlns='http://xml.python.org/'"
  388.         "     xmlns:foo='http://xml.python.org/'>"
  389.         "<foo:def/>"
  390.         "<ghi/>"
  391.         "</abc>", [
  392.             ("start", ("http://xml.python.org/", "abc"), "foo:abc"),
  393.             ("start", ("http://xml.python.org/", "def"), "foo:def"),
  394.             ("end", ("http://xml.python.org/", "def"), "foo:def"),
  395.             ("start", ("http://xml.python.org/", "ghi"), "foo:ghi"),
  396.             ("end", ("http://xml.python.org/", "ghi"), "foo:ghi"),
  397.             ("end", ("http://xml.python.org/", "abc"), "foo:abc"),
  398.             ])
  399.  
  400. def test_expat_nsdecl_pair_diff():
  401.     return check_expat_nsdecl(
  402.         "<abc xmlns='http://xml.python.org/1'"
  403.         "     xmlns:foo='http://xml.python.org/2'>"
  404.         "<foo:def/>"
  405.         "<ghi/>"
  406.         "</abc>", [
  407.             ("start", ("http://xml.python.org/1", "abc"), "abc"),
  408.             ("start", ("http://xml.python.org/2", "def"), "foo:def"),
  409.             ("end", ("http://xml.python.org/2", "def"), "foo:def"),
  410.             ("start", ("http://xml.python.org/1", "ghi"), "ghi"),
  411.             ("end", ("http://xml.python.org/1", "ghi"), "ghi"),
  412.             ("end", ("http://xml.python.org/1", "abc"), "abc"),
  413.             ])
  414.  
  415. # ===== InputSource support
  416.  
  417. xml_test_out = open(findfile("test"+os.extsep+"xml"+os.extsep+"out")).read()
  418.  
  419. def test_expat_inpsource_filename():
  420.     parser = create_parser()
  421.     result = StringIO()
  422.     xmlgen = XMLGenerator(result)
  423.  
  424.     parser.setContentHandler(xmlgen)
  425.     parser.parse(findfile("test"+os.extsep+"xml"))
  426.  
  427.     return result.getvalue() == xml_test_out
  428.  
  429. def test_expat_inpsource_sysid():
  430.     parser = create_parser()
  431.     result = StringIO()
  432.     xmlgen = XMLGenerator(result)
  433.  
  434.     parser.setContentHandler(xmlgen)
  435.     parser.parse(InputSource(findfile("test"+os.extsep+"xml")))
  436.  
  437.     return result.getvalue() == xml_test_out
  438.  
  439. def test_expat_inpsource_stream():
  440.     parser = create_parser()
  441.     result = StringIO()
  442.     xmlgen = XMLGenerator(result)
  443.  
  444.     parser.setContentHandler(xmlgen)
  445.     inpsrc = InputSource()
  446.     inpsrc.setByteStream(open(findfile("test"+os.extsep+"xml")))
  447.     parser.parse(inpsrc)
  448.  
  449.     return result.getvalue() == xml_test_out
  450.  
  451. # ===== IncrementalParser support
  452.  
  453. def test_expat_incremental():
  454.     result = StringIO()
  455.     xmlgen = XMLGenerator(result)
  456.     parser = create_parser()
  457.     parser.setContentHandler(xmlgen)
  458.  
  459.     parser.feed("<doc>")
  460.     parser.feed("</doc>")
  461.     parser.close()
  462.  
  463.     return result.getvalue() == start + "<doc></doc>"
  464.  
  465. def test_expat_incremental_reset():
  466.     result = StringIO()
  467.     xmlgen = XMLGenerator(result)
  468.     parser = create_parser()
  469.     parser.setContentHandler(xmlgen)
  470.  
  471.     parser.feed("<doc>")
  472.     parser.feed("text")
  473.  
  474.     result = StringIO()
  475.     xmlgen = XMLGenerator(result)
  476.     parser.setContentHandler(xmlgen)
  477.     parser.reset()
  478.  
  479.     parser.feed("<doc>")
  480.     parser.feed("text")
  481.     parser.feed("</doc>")
  482.     parser.close()
  483.  
  484.     return result.getvalue() == start + "<doc>text</doc>"
  485.  
  486. # ===== Locator support
  487.  
  488. def test_expat_locator_noinfo():
  489.     result = StringIO()
  490.     xmlgen = XMLGenerator(result)
  491.     parser = create_parser()
  492.     parser.setContentHandler(xmlgen)
  493.  
  494.     parser.feed("<doc>")
  495.     parser.feed("</doc>")
  496.     parser.close()
  497.  
  498.     return parser.getSystemId() is None and \
  499.            parser.getPublicId() is None and \
  500.            parser.getLineNumber() == 1
  501.  
  502. def test_expat_locator_withinfo():
  503.     result = StringIO()
  504.     xmlgen = XMLGenerator(result)
  505.     parser = create_parser()
  506.     parser.setContentHandler(xmlgen)
  507.     parser.parse(findfile("test.xml"))
  508.  
  509.     return parser.getSystemId() == findfile("test.xml") and \
  510.            parser.getPublicId() is None
  511.  
  512.  
  513. # ===========================================================================
  514. #
  515. #   error reporting
  516. #
  517. # ===========================================================================
  518.  
  519. def test_expat_inpsource_location():
  520.     parser = create_parser()
  521.     parser.setContentHandler(ContentHandler()) # do nothing
  522.     source = InputSource()
  523.     source.setByteStream(StringIO("<foo bar foobar>"))   #ill-formed
  524.     name = "a file name"
  525.     source.setSystemId(name)
  526.     try:
  527.         parser.parse(source)
  528.     except SAXException, e:
  529.         return e.getSystemId() == name
  530.  
  531. def test_expat_incomplete():
  532.     parser = create_parser()
  533.     parser.setContentHandler(ContentHandler()) # do nothing
  534.     try:
  535.         parser.parse(StringIO("<foo>"))
  536.     except SAXParseException:
  537.         return 1 # ok, error found
  538.     else:
  539.         return 0
  540.  
  541.  
  542. # ===========================================================================
  543. #
  544. #   xmlreader tests
  545. #
  546. # ===========================================================================
  547.  
  548. # ===== AttributesImpl
  549.  
  550. def verify_empty_attrs(attrs):
  551.     try:
  552.         attrs.getValue("attr")
  553.         gvk = 0
  554.     except KeyError:
  555.         gvk = 1
  556.  
  557.     try:
  558.         attrs.getValueByQName("attr")
  559.         gvqk = 0
  560.     except KeyError:
  561.         gvqk = 1
  562.  
  563.     try:
  564.         attrs.getNameByQName("attr")
  565.         gnqk = 0
  566.     except KeyError:
  567.         gnqk = 1
  568.  
  569.     try:
  570.         attrs.getQNameByName("attr")
  571.         gqnk = 0
  572.     except KeyError:
  573.         gqnk = 1
  574.  
  575.     try:
  576.         attrs["attr"]
  577.         gik = 0
  578.     except KeyError:
  579.         gik = 1
  580.  
  581.     return attrs.getLength() == 0 and \
  582.            attrs.getNames() == [] and \
  583.            attrs.getQNames() == [] and \
  584.            len(attrs) == 0 and \
  585.            not attrs.has_key("attr") and \
  586.            attrs.keys() == [] and \
  587.            attrs.get("attrs") is None and \
  588.            attrs.get("attrs", 25) == 25 and \
  589.            attrs.items() == [] and \
  590.            attrs.values() == [] and \
  591.            gvk and gvqk and gnqk and gik and gqnk
  592.  
  593. def verify_attrs_wattr(attrs):
  594.     return attrs.getLength() == 1 and \
  595.            attrs.getNames() == ["attr"] and \
  596.            attrs.getQNames() == ["attr"] and \
  597.            len(attrs) == 1 and \
  598.            attrs.has_key("attr") and \
  599.            attrs.keys() == ["attr"] and \
  600.            attrs.get("attr") == "val" and \
  601.            attrs.get("attr", 25) == "val" and \
  602.            attrs.items() == [("attr", "val")] and \
  603.            attrs.values() == ["val"] and \
  604.            attrs.getValue("attr") == "val" and \
  605.            attrs.getValueByQName("attr") == "val" and \
  606.            attrs.getNameByQName("attr") == "attr" and \
  607.            attrs["attr"] == "val" and \
  608.            attrs.getQNameByName("attr") == "attr"
  609.  
  610. def test_attrs_empty():
  611.     return verify_empty_attrs(AttributesImpl({}))
  612.  
  613. def test_attrs_wattr():
  614.     return verify_attrs_wattr(AttributesImpl({"attr" : "val"}))
  615.  
  616. # ===== AttributesImpl
  617.  
  618. def verify_empty_nsattrs(attrs):
  619.     try:
  620.         attrs.getValue((ns_uri, "attr"))
  621.         gvk = 0
  622.     except KeyError:
  623.         gvk = 1
  624.  
  625.     try:
  626.         attrs.getValueByQName("ns:attr")
  627.         gvqk = 0
  628.     except KeyError:
  629.         gvqk = 1
  630.  
  631.     try:
  632.         attrs.getNameByQName("ns:attr")
  633.         gnqk = 0
  634.     except KeyError:
  635.         gnqk = 1
  636.  
  637.     try:
  638.         attrs.getQNameByName((ns_uri, "attr"))
  639.         gqnk = 0
  640.     except KeyError:
  641.         gqnk = 1
  642.  
  643.     try:
  644.         attrs[(ns_uri, "attr")]
  645.         gik = 0
  646.     except KeyError:
  647.         gik = 1
  648.  
  649.     return attrs.getLength() == 0 and \
  650.            attrs.getNames() == [] and \
  651.            attrs.getQNames() == [] and \
  652.            len(attrs) == 0 and \
  653.            not attrs.has_key((ns_uri, "attr")) and \
  654.            attrs.keys() == [] and \
  655.            attrs.get((ns_uri, "attr")) is None and \
  656.            attrs.get((ns_uri, "attr"), 25) == 25 and \
  657.            attrs.items() == [] and \
  658.            attrs.values() == [] and \
  659.            gvk and gvqk and gnqk and gik and gqnk
  660.  
  661. def test_nsattrs_empty():
  662.     return verify_empty_nsattrs(AttributesNSImpl({}, {}))
  663.  
  664. def test_nsattrs_wattr():
  665.     attrs = AttributesNSImpl({(ns_uri, "attr") : "val"},
  666.                              {(ns_uri, "attr") : "ns:attr"})
  667.  
  668.     return attrs.getLength() == 1 and \
  669.            attrs.getNames() == [(ns_uri, "attr")] and \
  670.            attrs.getQNames() == ["ns:attr"] and \
  671.            len(attrs) == 1 and \
  672.            attrs.has_key((ns_uri, "attr")) and \
  673.            attrs.keys() == [(ns_uri, "attr")] and \
  674.            attrs.get((ns_uri, "attr")) == "val" and \
  675.            attrs.get((ns_uri, "attr"), 25) == "val" and \
  676.            attrs.items() == [((ns_uri, "attr"), "val")] and \
  677.            attrs.values() == ["val"] and \
  678.            attrs.getValue((ns_uri, "attr")) == "val" and \
  679.            attrs.getValueByQName("ns:attr") == "val" and \
  680.            attrs.getNameByQName("ns:attr") == (ns_uri, "attr") and \
  681.            attrs[(ns_uri, "attr")] == "val" and \
  682.            attrs.getQNameByName((ns_uri, "attr")) == "ns:attr"
  683.  
  684.  
  685. # ===== Main program
  686.  
  687. def make_test_output():
  688.     parser = create_parser()
  689.     result = StringIO()
  690.     xmlgen = XMLGenerator(result)
  691.  
  692.     parser.setContentHandler(xmlgen)
  693.     parser.parse(findfile("test"+os.extsep+"xml"))
  694.  
  695.     outf = open(findfile("test"+os.extsep+"xml"+os.extsep+"out"), "w")
  696.     outf.write(result.getvalue())
  697.     outf.close()
  698.  
  699. items = locals().items()
  700. items.sort()
  701. for (name, value) in items:
  702.     if name[ : 5] == "test_":
  703.         confirm(value(), name)
  704.  
  705. print "%d tests, %d failures" % (tests, fails)
  706. if fails != 0:
  707.     raise TestFailed, "%d of %d tests failed" % (fails, tests)
  708.